#include <muduo/net/TcpClient.h>
#include <muduo/net/TcpConnection.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/Buffer.h>
#include <muduo/base/CountDownLatch.h>
#include <muduo/net/EventLoopThread.h>
#include <iostream>
#include <string>
// Muduo是⼀个基于⾮阻塞IO和事件驱动的C++高并发TCP网络编程库。 它是⼀款基于主从Reactor模型的⽹络库，其使⽤的线程模型是one loop per thread, 所谓one loop per thread指的是：
// ⼀个线程只能有⼀个事件循环（EventLoop）， ⽤于响应计时器和IO事件
// ⼀个⽂件描述符只能由⼀个线程进⾏读写，换句话说就是⼀个TCP连接必须归属于某个EventLoop管理

//EventLoop类:主线程事件监控
//TcpServer类:线程事件监听

//使⽤Muduo网络库来实现⼀个简单英译汉服务器和客⼾端

class Client
{
private:
    //连接建立的回调
    void onConnection(const muduo::net::TcpConnectionPtr& conn)
    {
        if(conn->connected())
        {
            std::cout<<"连接成功"<<std::endl;
            _downlatch.countDown();//计数器--,为0的时候唤醒客户端
            _conn = conn;//获取到连接对象
        }
        else
        {
            std::cout<<"连接失败"<<std::endl;
            _conn.reset();//清理掉连接
        }
    }

    //消息的回调
    void onMessage(const muduo::net::TcpConnectionPtr & conn,muduo::net::Buffer * buf,muduo::Timestamp)
    {
        std::string msg = buf->retrieveAllAsString();//获取到服务端返回的内容
        std::cout<<msg<<std::endl;
    }
public:
    Client(const std::string & sip,uint16_t port)//服务端的ip和端口
    :_baseloop(_loopthread.startLoop()),//loopthread自动开启监控
    _client(_baseloop,muduo::net::InetAddress(sip,port),"DictClient")
    ,_downlatch(1)//初始化为1
    {
        _client.setConnectionCallback(std::bind(&Client::onConnection,this,std::placeholders::_1));
        _client.setMessageCallback(std::bind(&Client::onMessage,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));
        //连接服务器
        _client.connect();
        //等待->连接建立成功才继续往下
        _downlatch.wait();
    }

    bool Send(const std::string & msg)
    {
        if(_conn->connected() == false)
        {
            std::cout<<"连接断开,发送数据失败"<<std::endl;
            return false;
        }
        _conn->send(msg);
        return true;
    }

private:
    //开始事件监控
    muduo::net::EventLoopThread _loopthread;//让baseloop在线程进行监控
    muduo::net::EventLoop *_baseloop;
    muduo::net::TcpClient _client;//客户端
    muduo::net::TcpConnectionPtr _conn;//连接建立成功,发送信息
    muduo::CountDownLatch _downlatch;
};

int main()
{
    Client client("127.0.0.1",9090);
    while(true)
    {
        std::string msg;
        std::cin>>msg;
        client.Send(msg);
    }
    return 0;
}